home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fspdev / fspdevSetup.c < prev    next >
C/C++ Source or Header  |  1991-06-26  |  31KB  |  867 lines

  1. /* 
  2.  * fsPdevSetup.c --
  3.  *
  4.  *    Open/Close/Migration routines for pseudo-devices.
  5.  *    
  6.  *    There are three kinds of streams involved in the implementation,
  7.  *    a "control" stream that is returned to the server when it first
  8.  *    opens the pseudo-device.  When a client opens the pseudo-device
  9.  *    two streams are created and looked together.  The "client" stream
  10.  *    is returned to the client process, and the "server" stream is
  11.  *    passed to the server process via the control stream.
  12.  *
  13.  * Copyright 1987, 1988 Regents of the University of California
  14.  * Permission to use, copy, modify, and distribute this
  15.  * software and its documentation for any purpose and without
  16.  * fee is hereby granted, provided that the above copyright
  17.  * notice appear in all copies.  The University of California
  18.  * makes no representations about the suitability of this
  19.  * software for any purpose.  It is provided "as is" without
  20.  * express or implied warranty.
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /sprite/src/kernel/fspdev/RCS/fspdevSetup.c,v 9.6 91/06/26 01:05:40 mottsmth Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27. #include <sprite.h>
  28. #include <fs.h>
  29. #include <fsutil.h>
  30. #include <fsNameOps.h>
  31. #include <fsio.h>
  32. #include <fsconsist.h>
  33. #include <fsdm.h>
  34. #include <fsioLock.h>
  35. #include <proc.h>
  36. #include <rpc.h>
  37. #include <fspdevInt.h>
  38. #include <fspdev.h>
  39.  
  40. /*
  41.  *----------------------------------------------------------------------------
  42.  *
  43.  * FspdevNameOpen --
  44.  *
  45.  *    Early open time processing, this is called on a fileserver
  46.  *    when setting up state for a call to the CltOpen routines on
  47.  *    the client host.  For pseudo-device server processes, which
  48.  *    are indicated by the FS_PDEV_MASTER flag, check that no other
  49.  *    server exists.  For all other processes, which are referred to
  50.  *    as "clients", make sure that a server process exists and
  51.  *    generate a new ioFileID for the connection between the client
  52.  *    and the server.
  53.  *
  54.  * Results:
  55.  *    For server processes, SUCCESS if it is now the server,
  56.  *    FS_FILE_BUSY if there already exists a server process.  For
  57.  *    clients, SUCCESS if there is a server or the parameters
  58.  *    indicate this is only for get/set attributes, DEV_OFFLINE if
  59.  *    there is no server. 
  60.  *
  61.  * Side effects:
  62.  *    Save the hostID of the calling process if
  63.  *    it is to be the server for the pseudo-device.
  64.  *
  65.  *----------------------------------------------------------------------------
  66.  *
  67.  */
  68. ReturnStatus
  69. FspdevNameOpen(handlePtr, openArgsPtr, openResultsPtr)
  70.      register Fsio_FileIOHandle *handlePtr;    /* A handle from FslclLookup.
  71.                      * Should be LOCKED upon entry,
  72.                      * unlocked upon exit. */
  73.      Fs_OpenArgs        *openArgsPtr;    /* Standard open arguments */
  74.      Fs_OpenResults    *openResultsPtr;/* For returning ioFileID, streamID,
  75.                      * and Fsio_DeviceState */
  76. {
  77.     register    ReturnStatus status = SUCCESS;
  78.     Fs_FileID    ioFileID;
  79.     register    Fspdev_ControlIOHandle *ctrlHandlePtr;
  80.     register    Fs_Stream *streamPtr;
  81.     register    Fspdev_State *pdevStatePtr;
  82.  
  83.     /*
  84.      * The control I/O handle is identified by the fileID of the pseudo-device
  85.      * file with type CONTROL, and with the decriptor version number
  86.      * xor'ed into the minor number to avoid conflict when you delete the
  87.      * pdev file and recreate one with the same file number (minor field).
  88.      */
  89.     ioFileID = handlePtr->hdr.fileID;
  90.     ioFileID.type = FSIO_CONTROL_STREAM;
  91.     ioFileID.serverID = rpc_SpriteID;
  92.     ioFileID.major = handlePtr->hdr.fileID.major;
  93.     ioFileID.minor = handlePtr->hdr.fileID.minor ^
  94.             (handlePtr->descPtr->version << 16);
  95.     ctrlHandlePtr = FspdevControlHandleInit(&ioFileID, handlePtr->hdr.name);
  96.  
  97.     if (openArgsPtr->useFlags & FS_PDEV_MASTER) {
  98.     /*
  99.      * When a server opens we ensure there is only one.
  100.      */
  101.     if (ctrlHandlePtr->serverID != NIL) {
  102.         status = FS_FILE_BUSY;
  103.     } else {
  104.         /*
  105.          * Note which host is running the pseudo-device server.
  106.          */
  107.         ctrlHandlePtr->serverID = openArgsPtr->clientID;
  108.         /*
  109.          * Note our hostID is still in the hdr.serverID field of the
  110.          * control handle being returned to the opening process. This is
  111.          * used when closing the control stream to get back to us
  112.          * so we can clear the serverID field here.  We also set up
  113.          * a shadow stream here, which has us as the server so
  114.          * recovery and closing work right.
  115.          */
  116.         openResultsPtr->ioFileID = ioFileID;
  117.         openResultsPtr->streamData = (ClientData)NIL;
  118.         openResultsPtr->dataSize = 0;
  119.         streamPtr = Fsio_StreamCreate(rpc_SpriteID, openArgsPtr->clientID,
  120.                     (Fs_HandleHeader *)ctrlHandlePtr,
  121.                     openArgsPtr->useFlags, handlePtr->hdr.name);
  122.         openResultsPtr->streamID = streamPtr->hdr.fileID;
  123.         Fsutil_HandleRelease(streamPtr, TRUE);
  124.     }
  125.     } else {
  126.     if (openArgsPtr->useFlags == 0) {
  127.         /*
  128.          * Set up for get/set attributes.  We point the client
  129.          * at the name of the pseudo-device if it is not active,
  130.          * otherwise we point it at the control stream handle that
  131.          * has the current access and modify times.
  132.          */
  133.         if (ctrlHandlePtr->serverID == NIL) {
  134.         openResultsPtr->ioFileID = handlePtr->hdr.fileID;
  135.         } else {
  136.         openResultsPtr->ioFileID = ctrlHandlePtr->rmt.hdr.fileID;
  137.         if (openArgsPtr->clientID != ctrlHandlePtr->serverID) {
  138.             /*
  139.              * The requesting client is different than the pdev
  140.              * server host.  Unfortunately the serverID in the
  141.              * control handle is us, the file server.  We have
  142.              * to hack the fileID so the client makes the RPC to
  143.              * the pdev server.  This relies on a parallel hack
  144.              * in Fsrmt_GetIOAttr to fix up the serverID by
  145.              * using the Fs_Attributes.serverID, which is us,
  146.              * so that the correct control handle is found.
  147.              */
  148.             openResultsPtr->ioFileID.type = FSIO_RMT_CONTROL_STREAM;
  149.             openResultsPtr->ioFileID.serverID = ctrlHandlePtr->serverID;
  150.         }
  151.         }
  152.     } else if (ctrlHandlePtr->serverID == NIL) {
  153.         /*
  154.          * No server process.
  155.          */
  156.         status = DEV_OFFLINE;
  157.     } else {
  158.         /*
  159.          * The server exists.  Create a new I/O handle for the client.
  160.          * The major and minor numbers are generated from the fileID
  161.          * of the pseudo-device name (to avoid conflict with other
  162.          * pseudo-devices) and a clone seed (to avoid conflict with
  163.          * other clients of this pseudo-device).
  164.          */
  165.         if (ctrlHandlePtr->serverID == openArgsPtr->clientID) {
  166.         openResultsPtr->ioFileID.type = FSIO_LCL_PSEUDO_STREAM;
  167.         } else {
  168.         openResultsPtr->ioFileID.type = FSIO_RMT_PSEUDO_STREAM;
  169.         }
  170.         openResultsPtr->ioFileID.serverID = ctrlHandlePtr->serverID;
  171.         openResultsPtr->ioFileID.major =
  172.                 (handlePtr->hdr.fileID.serverID << 16) |
  173.                  handlePtr->hdr.fileID.major;
  174.         ctrlHandlePtr->seed++;
  175.         openResultsPtr->ioFileID.minor =
  176.                 ((handlePtr->descPtr->version << 24) ^
  177.                  (handlePtr->hdr.fileID.minor << 12)) |
  178.                  ctrlHandlePtr->seed;
  179.         /*
  180.          * Return the control stream file ID so it can be found again
  181.          * later when setting up the client's stream and the
  182.          * corresponding server stream.  The procID and uid fields are
  183.          * extra here, but will be used later if the client is remote.
  184.          */
  185.         pdevStatePtr = mnew(Fspdev_State);
  186.         pdevStatePtr->ctrlFileID = ctrlHandlePtr->rmt.hdr.fileID;
  187.         pdevStatePtr->procID = (Proc_PID)NIL;
  188.         pdevStatePtr->uid = NIL;
  189.         openResultsPtr->streamData = (ClientData)pdevStatePtr ;
  190.         openResultsPtr->dataSize = sizeof(Fspdev_State);
  191.         /*
  192.          * Create a streamID for the opening process.  No shadow
  193.          * stream is kept here.  Instead, the streamID is returned to
  194.          * the pdev server who sets up the shadow stream.
  195.          */
  196.         Fsio_StreamCreateID(ctrlHandlePtr->serverID, &openResultsPtr->streamID);
  197.         pdevStatePtr->streamID = openResultsPtr->streamID;
  198.     }
  199.     }
  200.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  201.     Fsutil_HandleUnlock(handlePtr);
  202.     return(status);
  203. }
  204.  
  205. /*
  206.  *----------------------------------------------------------------------
  207.  *
  208.  * FspdevPseudoStreamIoOpen --
  209.  *
  210.  *    This is called from Fs_Open, or from the RPC stub if the client
  211.  *    is remote, to complete setup of a client's
  212.  *    stream to the pseudo-device.  The server is running on this
  213.  *    host.  This routine creates a trivial client I/O handle
  214.  *    that references the server's I/O handle that has the main
  215.  *    state for the connection to the server.  FspdevServerStreamCreate
  216.  *    is then called to set up the server's I/O handle, and the control
  217.  *    stream is used to pass a server stream to the server.  Finally
  218.  *    an open transaction is made with the server process
  219.  *    to see if it will accept the client.
  220.  * 
  221.  * Results:
  222.  *    SUCCESS, unless the server process has died recently, or the
  223.  *    server rejects the open.
  224.  *
  225.  * Side effects:
  226.  *    Creates the client's I/O handle.  Calls FspdevServerStreamCreate
  227.  *    which sets up the servers corresponding I/O handle.
  228.  *
  229.  *----------------------------------------------------------------------
  230.  */
  231.  
  232. ReturnStatus
  233. FspdevPseudoStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  234.     ioHandlePtrPtr)
  235.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  236.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  237.     int            clientID;    /* Host doing the open */
  238.     ClientData        streamData;    /* Pointer to Fspdev_State. */
  239.     char        *name;        /* File name for error msgs */
  240.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  241.                      * I/O to a pseudo device, or NIL */
  242. {
  243.     ReturnStatus        status;
  244.     Boolean            foundStream;
  245.     register Fspdev_ClientIOHandle    *cltHandlePtr;
  246.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  247.     register Fspdev_State    *pdevStatePtr;
  248.     Fs_Stream            *cltStreamPtr;
  249.     Fs_Stream            *srvStreamPtr;
  250.     FspdevNotify            *notifyPtr;
  251.     Proc_ControlBlock        *procPtr;
  252.     Proc_PID             procID;
  253.     int                uid;
  254.  
  255.     pdevStatePtr = (Fspdev_State *)streamData;
  256.     ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle,
  257.                     &pdevStatePtr->ctrlFileID);
  258.     /*
  259.      * If there is no server present the creation of the stream
  260.      * can't succeed.  This case arises when the pseudo-device
  261.      * master goes away between FspdevNameOpen and this call.
  262.      */
  263.     if ((ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) ||
  264.     (ctrlHandlePtr->serverID == NIL)) {
  265.     status = DEV_OFFLINE;
  266.     goto exit;
  267.     }
  268.  
  269.     if (ctrlHandlePtr->rmt.hdr.fileID.serverID != rpc_SpriteID) {
  270.     /*
  271.      * Extract the seed from the minor field (see the SrvOpen routine).
  272.      * This done in case of recovery when we'll need to reset the
  273.      * seed kept on the file server.
  274.      */
  275.     ctrlHandlePtr->seed = ioFileIDPtr->minor & 0x0FFF;
  276.     }
  277.  
  278.     cltHandlePtr = FspdevConnect(ctrlHandlePtr, ioFileIDPtr, clientID, 0);
  279.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  280.     status = DEV_OFFLINE;
  281.     goto exit;
  282.     }
  283.     /*
  284.      * Put the client on its own stream list.
  285.      */
  286.     cltStreamPtr = Fsio_StreamAddClient(&pdevStatePtr->streamID, clientID,
  287.         (Fs_HandleHeader *)cltHandlePtr, *flagsPtr, name,
  288.         (Boolean *)NIL, &foundStream);
  289.     Fsutil_HandleRelease(cltStreamPtr, TRUE);
  290.     Fsutil_HandleUnlock(cltHandlePtr);
  291.     /*
  292.      * Set up a stream for the server process.  This will be picked
  293.      * up by FspdevControlRead and converted to a user-level streamID.
  294.      */
  295.     srvStreamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
  296.                 (Fs_HandleHeader *)cltHandlePtr->pdevHandlePtr,
  297.                 FS_READ|FS_USER, name);
  298.     notifyPtr = mnew(FspdevNotify);
  299.     notifyPtr->streamPtr = srvStreamPtr;
  300.     List_InitElement((List_Links *)notifyPtr);
  301.     List_Insert((List_Links *)notifyPtr,
  302.         LIST_ATREAR(&ctrlHandlePtr->queueHdr));
  303.     Fsutil_HandleUnlock(srvStreamPtr);
  304.  
  305.     Fsutil_FastWaitListNotify(&ctrlHandlePtr->readWaitList);
  306.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  307.     ctrlHandlePtr = (Fspdev_ControlIOHandle *)NIL;
  308.     /*
  309.      * Now that the request response stream is set up we do
  310.      * our first transaction with the server process to see if it
  311.      * will accept the open.  We unlock the handle and rely on the
  312.      * per-connection monitor lock instead.  This is important because a
  313.      * buggy pseudo-device server could be ignoring this connection
  314.      * request indefinitely, and leaving handles locked for long periods
  315.      * clogs up handle scavenging, and potentially recovery callbacks too.
  316.      */
  317.     if (clientID == rpc_SpriteID) {
  318.     procPtr = Proc_GetEffectiveProc();
  319.     procID = procPtr->processID;
  320.     uid = procPtr->effectiveUserID;
  321.     } else {
  322.     procID = pdevStatePtr->procID;
  323.     uid = pdevStatePtr->uid;
  324.     }
  325.     status = FspdevPseudoStreamOpen(cltHandlePtr->pdevHandlePtr, *flagsPtr,
  326.                 clientID, procID, uid);
  327.     if (status == SUCCESS) {
  328.     *ioHandlePtrPtr = (Fs_HandleHeader *)cltHandlePtr;
  329.     } else {
  330.     /*
  331.      * Clean up client side, we assume server closes its half.
  332.      */
  333.     Fsutil_HandleInvalidate((Fs_HandleHeader *) cltHandlePtr);
  334.     Fsutil_HandleRemove(cltHandlePtr);
  335.     (void)Fsio_StreamClientClose(&cltStreamPtr->clientList, clientID);
  336.     if (!foundStream) {
  337.         /*
  338.          * The client's stream wasn't already around from being installed
  339.          * in Fs_Open, so we nuke the shadow stream we've created.
  340.          */
  341.         cltStreamPtr = Fsutil_HandleFetchType(Fs_Stream,
  342.                          &cltStreamPtr->hdr.fileID);
  343.         Fsio_StreamDestroy(cltStreamPtr);
  344.     }
  345.     }
  346. exit:
  347.     if (ctrlHandlePtr != (Fspdev_ControlIOHandle *)NIL) {
  348.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  349.     }
  350.     free((Address)streamData);
  351.     return(status);
  352. }
  353.  
  354. /*
  355.  *----------------------------------------------------------------------
  356.  *
  357.  * FspdevConnect --
  358.  *
  359.  *    This sets up a pseduo-device connection.  This is called from
  360.  *    the PseudoStreamCltOpen routine with ordinary pseudo-devices,
  361.  *    and from FspdevPfsIoOpen to set up the naming connection to a
  362.  *    pseudo-filesystem server, and during an IOC_PFS_OPEN by a
  363.  *    pseudo-filesystem server to set up a connection to a client.
  364.  *    The case of the naming stream is distinguished by the last
  365.  *    parameter.  The state of this needs to be marked specially
  366.  *    so proper clean up can be made later.
  367.  * 
  368.  * Results:
  369.  *    A pointer to a Fspdev_ClientIOHandle that references a Fspdev_ServerIOHandle.
  370.  *    The client handle is returned locked, but the server handle it
  371.  *    references is not locked.
  372.  *
  373.  * Side effects:
  374.  *    Creates the client's I/O handle.  Calls FspdevServerStreamCreate
  375.  *    which sets up the servers corresponding I/O handle.
  376.  *    This changes the ioFileIDPtr->type from FSIO_LCL_PSEUDO_STREAM to
  377.  *    FSIO_SERVER_STREAM.
  378.  *
  379.  *----------------------------------------------------------------------
  380.  */
  381.  
  382. Fspdev_ClientIOHandle *
  383. FspdevConnect(ctrlHandlePtr, ioFileIDPtr, clientID, naming)
  384.     Fspdev_ControlIOHandle *ctrlHandlePtr;    /* Control stream handle */
  385.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  386.     int            clientID;    /* Host ID of client-side */
  387.     Boolean        naming;        /* TRUE if called from FspdevPfsIoOpen
  388.                      * to set up the naming stream */
  389. {
  390.     Boolean            found;
  391.     Fs_HandleHeader        *hdrPtr;
  392.     register Fspdev_ClientIOHandle    *cltHandlePtr;
  393.  
  394.     found = Fsutil_HandleInstall(ioFileIDPtr, sizeof(Fspdev_ClientIOHandle),
  395.         ctrlHandlePtr->rmt.hdr.name, FALSE, &hdrPtr);
  396.     cltHandlePtr = (Fspdev_ClientIOHandle *)hdrPtr;
  397.     if (found) {
  398.     if ((cltHandlePtr->pdevHandlePtr != (Fspdev_ServerIOHandle *)NIL) &&
  399.         (cltHandlePtr->pdevHandlePtr->clientPID != (unsigned int)NIL)) {
  400.         printf(
  401.         "FspdevConnect found client handle\n");
  402.         printf("Check (and kill) client process %x\n",
  403.         cltHandlePtr->pdevHandlePtr->clientPID);
  404.     }
  405.     /*
  406.      * Invalidate this lingering handle.  The client process is hung
  407.      * or suspended and hasn't closed its end of the pdev connection.
  408.      */
  409.     Fsutil_HandleInvalidate((Fs_HandleHeader *)cltHandlePtr);
  410.     Fsutil_HandleRelease(cltHandlePtr, TRUE);
  411.  
  412.     found = Fsutil_HandleInstall(ioFileIDPtr, sizeof(Fspdev_ClientIOHandle),
  413.             ctrlHandlePtr->rmt.hdr.name, FALSE, &hdrPtr);
  414.     cltHandlePtr = (Fspdev_ClientIOHandle *)hdrPtr;
  415.     if (found) {
  416.         panic( "FspdevConnect handle still there\n");
  417.     }
  418.     }
  419.     /*
  420.      * Set up the connection state and hook the client handle to it.
  421.      */
  422.     cltHandlePtr->pdevHandlePtr = FspdevServerStreamCreate(ioFileIDPtr,
  423.                     ctrlHandlePtr->rmt.hdr.name, naming);
  424.     if (cltHandlePtr->pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  425.     Fsutil_HandleRemove(cltHandlePtr);
  426.     return((Fspdev_ClientIOHandle *)NIL);
  427.     }
  428.     cltHandlePtr->pdevHandlePtr->ctrlHandlePtr = ctrlHandlePtr;
  429.     cltHandlePtr->segPtr = (struct Vm_Segment *)NIL; /* JMS */
  430.     /*
  431.      * Set up the client list in case the client is remote.
  432.      */
  433.     List_Init(&cltHandlePtr->clientList);
  434.     (void)Fsconsist_IOClientOpen(&cltHandlePtr->clientList, clientID, 0, FALSE);
  435.     /*
  436.      * Grab an extra reference to the server's handle so the
  437.      * server close routine can remove the handle and it won't
  438.      * go away until the client also closes.
  439.      */
  440.     Fsutil_HandleUnlock(cltHandlePtr->pdevHandlePtr);
  441.     (void)Fsutil_HandleDup((Fs_HandleHeader *)cltHandlePtr->pdevHandlePtr);
  442.     Fsutil_HandleUnlock(cltHandlePtr->pdevHandlePtr);
  443.  
  444.     return(cltHandlePtr);
  445. }
  446.  
  447. /*
  448.  *----------------------------------------------------------------------
  449.  *
  450.  * FspdevRmtPseudoStreamIoOpen --
  451.  *
  452.  *    Complete a remote client's stream to a pseudo-device.
  453.  *    The client is on a different host than the server process.  This
  454.  *    makes an RPC to the pseudo-device server's host to invoke
  455.  *    FspdevPseudoStreamIoOpen, which sets up the pdev connection.
  456.  *    This host only keeps a Fsrmt_IOHandle that implicitly references
  457.  *    the pdev connection on the pdev server's host.
  458.  * 
  459.  * Results:
  460.  *    SUCCESS unless the server process has died recently, then DEV_OFFLINE.
  461.  *
  462.  * Side effects:
  463.  *    RPC to the server's host to invoke the regular setup routines.
  464.  *
  465.  *----------------------------------------------------------------------
  466.  */
  467. /*ARGSUSED*/
  468. ReturnStatus
  469. FspdevRmtPseudoStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  470.     ioHandlePtrPtr)
  471.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  472.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  473.     int            clientID;    /* IGNORED (== rpc_SpriteID) */
  474.     ClientData        streamData;    /* NIL for us. */
  475.     char        *name;        /* File name for error msgs */
  476.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  477.                      * I/O to a pseudo device, or NIL */
  478. {
  479.     register ReturnStatus status;
  480.     register Proc_ControlBlock *procPtr;
  481.     register Fspdev_State *pdevStatePtr = (Fspdev_State *)streamData;
  482.  
  483.     /*
  484.      * Use RPC to invoke FspdevPseudoStreamIoOpen which sets up the connection.
  485.      */
  486.     procPtr = Proc_GetEffectiveProc();
  487.     pdevStatePtr->procID = procPtr->processID;
  488.     pdevStatePtr->uid = procPtr->effectiveUserID;
  489.     ioFileIDPtr->type = FSIO_LCL_PSEUDO_STREAM;
  490.     status = Fsrmt_DeviceOpen(ioFileIDPtr, *flagsPtr,    sizeof(Fspdev_State),
  491.                 (ClientData)pdevStatePtr);
  492.     if (status == SUCCESS) {
  493.     ioFileIDPtr->type = FSIO_RMT_PSEUDO_STREAM;
  494.     Fsrmt_IOHandleInit(ioFileIDPtr, *flagsPtr, name, ioHandlePtrPtr);
  495.     }
  496.     free((Address)pdevStatePtr);
  497.     return(status);
  498. }
  499.  
  500. /*
  501.  *----------------------------------------------------------------------
  502.  *
  503.  * FspdevPseudoStreamClose --
  504.  *
  505.  *    Close a pseudo stream that's been used by a client to talk to a server.
  506.  *    This issues a close message to the server and then tears down the
  507.  *    state used to implement the pseudo stream connection.
  508.  *
  509.  * Results:
  510.  *    SUCCESS.
  511.  *
  512.  * Side effects:
  513.  *    Other than the request-response to the server, this releases the
  514.  *    pseudo stream's reference to the handle.  This may also have
  515.  *    to contact a remote host to clean up references there, too.
  516.  *
  517.  *----------------------------------------------------------------------
  518.  */
  519. /*ARGSUSED*/
  520. #ifndef SOSP91
  521. ReturnStatus
  522. FspdevPseudoStreamClose(streamPtr, clientID, procID, flags, size, data)
  523. #else
  524. ReturnStatus
  525. FspdevPseudoStreamClose(streamPtr, clientID, procID, flags, size, data,
  526.     offsetPtr, rwFlagsPtr)
  527. #endif
  528.     Fs_Stream        *streamPtr;    /* Client pseudo-stream to close */
  529.     int            clientID;    /* HostID of client closing */
  530.     Proc_PID        procID;        /* ID of closing process, IGNORED */
  531.     int            flags;        /* IGNORED */
  532.     int            size;        /* Should be zero */
  533.     ClientData        data;        /* IGNORED */
  534. #ifdef SOSP91
  535.     int            *offsetPtr;
  536.     int            *rwFlagsPtr;
  537. #endif
  538. {
  539.     register Fspdev_ClientIOHandle *cltHandlePtr =
  540.         (Fspdev_ClientIOHandle *)streamPtr->ioHandlePtr;
  541.     Boolean cache = FALSE;
  542.  
  543.     DBG_PRINT( ("Client closing pdev %x,%x\n", 
  544.         cltHandlePtr->hdr.fileID.major,
  545.         cltHandlePtr->hdr.fileID.minor) );
  546.  
  547.     if (!Fsconsist_IOClientClose(&cltHandlePtr->clientList, clientID, 0, &cache)) {
  548.     /*
  549.      * Invalid client trying to close.
  550.      */
  551.     printf( "FspdevPseudoStreamClose: client %d not found\n",
  552.         clientID);
  553.     Fsutil_HandleUnlock(cltHandlePtr);
  554.     return(GEN_INVALID_ARG);
  555.     } else if (!List_IsEmpty(&cltHandlePtr->clientList)) {
  556.     /*
  557.      * Still clients out there.
  558.      */
  559.     Fsutil_HandleUnlock(cltHandlePtr);
  560.     } else {
  561.     /*
  562.      * No clients remaining so we can close down the connection.
  563.      * Notify the server that a client has gone away.  Then we get rid
  564.      * of our reference to the server's handle and nuke our own.
  565.      * Note we unlock the client handle before the request response
  566.      * in case the server process is buggy and hangs us.
  567.      */
  568.     Fsutil_HandleUnlock(cltHandlePtr);
  569.     FspdevPseudoStreamCloseInt(cltHandlePtr->pdevHandlePtr);
  570.     Fsutil_HandleRelease(cltHandlePtr->pdevHandlePtr, FALSE);
  571.     Fsutil_HandleRelease(cltHandlePtr, FALSE);
  572.     Fsutil_HandleRemove(cltHandlePtr);
  573.     }
  574.     return(SUCCESS);
  575. }
  576.  
  577. /*
  578.  *----------------------------------------------------------------------
  579.  *
  580.  * FspdevPseudoStreamMigClose --
  581.  *
  582.  *    Called to release a reference on a pseudo stream.  However, there
  583.  *    is always only one refernece on the handle so we do nothing.
  584.  *
  585.  * Results:
  586.  *    SUCCESS.
  587.  *
  588.  * Side effects:
  589.  *    Release the I/O handle.
  590.  *
  591.  *----------------------------------------------------------------------
  592.  */
  593. /*ARGSUSED*/
  594. ReturnStatus
  595. FspdevPseudoStreamMigClose(hdrPtr, flags)
  596.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  597.     int flags;            /* Use flags from the stream */
  598. {
  599.     panic( "FspdevPseudoStreamMigClose called\n");
  600.  
  601.     return(SUCCESS);
  602. }
  603.  
  604. /*
  605.  *----------------------------------------------------------------------
  606.  *
  607.  * FspdevPseudoStreamMigrate --
  608.  *
  609.  *    Migrate a pseudo-stream client.
  610.  *
  611.  *    This takes care of transfering references from one client to the other.
  612.  *    A useful side-effect of this routine is    to properly set the type in
  613.  *    the ioFileID, either FSIO_LCL_PSEUDO_STREAM or FSIO_RMT_PSEUDO_STREAM.
  614.  *    In the latter case FspdevRmtPseudoStreamMigrate is called to do all
  615.  *    the work.
  616.  *
  617.  * Results:
  618.  *    An error status if the I/O handle can't be set-up.
  619.  *    Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
  620.  *    bit set, and *sizePtr and *dataPtr are set to reference Fspdev_State.
  621.  *
  622.  * Side effects:
  623.  *    Sets the correct stream type on the ioFileID.
  624.  *    Shifts client references from the srcClient to the destClient.
  625.  *    Set up and return Fspdev_State for use by the MigEnd routine.
  626.  
  627.  *
  628.  *----------------------------------------------------------------------
  629.  */
  630. /*ARGSUSED*/
  631. ReturnStatus
  632. FspdevPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr,
  633.               dataPtr)
  634.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  635.     int        dstClientID;    /* ID of target client */
  636.     int        *flagsPtr;    /* In/Out Stream usage flags */
  637.     int        *offsetPtr;    /* Return - new stream offset */
  638.     int        *sizePtr;    /* Return - sizeof(Fspdev_State) */
  639.     Address    *dataPtr;    /* Return - pointer to Fspdev_State */
  640. {
  641.     Fspdev_ClientIOHandle            *cltHandlePtr;
  642.     Boolean                closeSrcClient;
  643.  
  644.     if (migInfoPtr->ioFileID.serverID != rpc_SpriteID) {
  645.     /*
  646.      * The device was local, which is why we were called, but is
  647.      * now remote.
  648.      */
  649.     migInfoPtr->ioFileID.type = FSIO_RMT_PSEUDO_STREAM;
  650.     return(FspdevRmtPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr,
  651.                     offsetPtr, sizePtr, dataPtr));
  652.     }
  653.     migInfoPtr->ioFileID.type = FSIO_LCL_PSEUDO_STREAM;
  654.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, &migInfoPtr->ioFileID);
  655.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  656.     panic( "FspdevPseudoStreamMigrate, no client handle <%d,%x,%x>\n",
  657.         migInfoPtr->ioFileID.serverID,
  658.         migInfoPtr->ioFileID.major, migInfoPtr->ioFileID.minor);
  659.     return(FAILURE);
  660.     }
  661.     DBG_PRINT( ("Migrating pdev %x,%x, ref %d.\n", 
  662.         cltHandlePtr->hdr.fileID.major,
  663.         cltHandlePtr->hdr.fileID.minor,
  664.         cltHandlePtr->hdr.refCount) );
  665.     /*
  666.      * At the stream level, add the new client to the set of clients
  667.      * for the stream, and check for any cross-network stream sharing.
  668.      */
  669.     Fsio_StreamMigClient(migInfoPtr, dstClientID, (Fs_HandleHeader *)cltHandlePtr,
  670.             &closeSrcClient);
  671.  
  672.     /*
  673.      * Move the client at the I/O handle level.  The flags are used
  674.      * by FsIOClient{Open,Close} and are different for pdevs than
  675.      * other files -- namely, the flags are set to 0 before calls to these
  676.      * routines.  The only flag we have to make sure to pass is
  677.      * whether it's a new stream, since this is used by Fsio_MigrateClient
  678.      * itself.
  679.      */
  680.     Fsio_MigrateClient(&cltHandlePtr->clientList, migInfoPtr->srcClientID,
  681.               dstClientID, (int)(migInfoPtr->flags & FS_NEW_STREAM),
  682.               closeSrcClient);
  683.  
  684.     *sizePtr = 0;
  685.     *dataPtr = (Address)NIL;
  686.     *flagsPtr = migInfoPtr->flags;
  687.     *offsetPtr = migInfoPtr->offset;
  688.     /*
  689.      * We don't need this reference on the I/O handle; there is no change.
  690.      */
  691.     Fsutil_HandleRelease(cltHandlePtr, TRUE);
  692.     return(SUCCESS);
  693. }
  694.  
  695. /*
  696.  *----------------------------------------------------------------------
  697.  *
  698.  * FspdevRmtPseudoStreamMigrate --
  699.  *
  700.  *    Migrate a pseudo-stream client.
  701.  *    This takes care of transfering references from one client to the other.
  702.  *    A useful side-effect of this routine is    to properly set the type in
  703.  *    the ioFileID, either FSIO_LCL_PSEUDO_STREAM or FSIO_RMT_PSEUDO_STREAM.
  704.  *    In the former case FspdevPseudoStreamMigrate is called to do all the work.
  705.  *
  706.  * Results:
  707.  *    An error status if the I/O handle can't be set-up.
  708.  *    Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
  709.  *    bit set, and *sizePtr and *dataPtr are set to reference Fspdev_State.
  710.  *
  711.  * Side effects:
  712.  *    Sets the correct stream type on the ioFileID.
  713.  *    Shifts client references from the srcClient to the destClient.
  714.  *
  715.  *----------------------------------------------------------------------
  716.  */
  717. /*ARGSUSED*/
  718. ReturnStatus
  719. FspdevRmtPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  720.              sizePtr, dataPtr)
  721.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  722.     int        dstClientID;    /* ID of target client */
  723.     int        *flagsPtr;    /* In/Out Stream usage flags */
  724.     int        *offsetPtr;    /* Return - the new stream offset */
  725.     int        *sizePtr;    /* Return - 0 */
  726.     Address    *dataPtr;    /* Return - NIL */
  727. {
  728.     register ReturnStatus        status;
  729.  
  730.     if (migInfoPtr->ioFileID.serverID == rpc_SpriteID) {
  731.     /*
  732.      * The device was remote, which is why we were called, but is now local.
  733.      */
  734.     migInfoPtr->ioFileID.type = FSIO_LCL_PSEUDO_STREAM;
  735.     return(FspdevPseudoStreamMigrate(migInfoPtr, dstClientID, flagsPtr,
  736.                      offsetPtr, sizePtr, dataPtr));
  737.     }
  738.     migInfoPtr->ioFileID.type = FSIO_RMT_PSEUDO_STREAM;
  739.     status = Fsrmt_NotifyOfMigration(migInfoPtr, flagsPtr, offsetPtr,
  740.                 0, (Address)NIL);
  741.     DBG_PRINT( ("Migrating remote pdev %x,%x.\n", 
  742.         migInfoPtr->ioFileID.major,
  743.         migInfoPtr->ioFileID.minor) );
  744.     if (status != SUCCESS) {
  745.     printf( "FsrmtDeviceMigrate, server error <%x>\n",
  746.         status);
  747.     } else {
  748.     *dataPtr = (Address)NIL;
  749.     *sizePtr = 0;
  750.     }
  751.     return(status);
  752. }
  753.  
  754. /*
  755.  *----------------------------------------------------------------------
  756.  *
  757.  * FspdevPseudoStreamMigOpen --
  758.  *
  759.  *    Complete setup of a pdev client I/O handle after migrating a stream
  760.  *    to the I/O server of the pseudo-device connection (the host running
  761.  *    the user-level server process).  FspdevPseudoStreamMigrate has done
  762.  *    the work of shifting use counts at the stream and I/O handle level.
  763.  *    This routine fills in the stream's ioHandlePtr, but doens't adjust
  764.  *    the low-level reference count on the I/O handle (like other MigEnd
  765.  *    procedures) because the reference count isn't used the same way.
  766.  *    With pseudo-device connections, there is always only one refCount
  767.  *    on the client handle, but there may be entries in the clientList
  768.  *    to reflect remote clients.
  769.  *
  770.  * Results:
  771.  *    None.
  772.  *
  773.  * Side effects:
  774.  *    None.
  775.  *
  776.  *----------------------------------------------------------------------
  777.  */
  778. /*ARGSUSED*/
  779. ReturnStatus
  780. FspdevPseudoStreamMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  781.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  782.     int        size;        /* Zero */
  783.     ClientData    data;        /* NIL */
  784.     Fs_HandleHeader **hdrPtrPtr;    /* Return - handle for the file */
  785. {
  786.     register Fspdev_ClientIOHandle *cltHandlePtr;
  787.  
  788.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle,
  789.                      &migInfoPtr->ioFileID);
  790.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  791.     panic( "FspdevPseudoStreamMigOpen, no handle.\n");
  792.     return(FAILURE);
  793.     } else {
  794.     /*
  795.      * Release this reference so the client handle always has
  796.      * just one reference.  Instead of refcounts, an empty
  797.      * client list indicates there are no more clients.
  798.      */
  799.     Fsutil_HandleRelease(cltHandlePtr, TRUE);
  800.     *hdrPtrPtr = (Fs_HandleHeader *)cltHandlePtr;
  801.     return(SUCCESS);
  802.     }
  803. }
  804.  
  805. /*
  806.  *----------------------------------------------------------------------
  807.  *
  808.  * FspdevRmtPseudoStreamVerify --
  809.  *
  810.  *    Verify that the remote client is known for the pdev, and return
  811.  *    a locked pointer to the client I/O handle.
  812.  *
  813.  * Results:
  814.  *    A pointer to the client I/O handle, or NIL if
  815.  *    the client is bad.
  816.  *
  817.  * Side effects:
  818.  *    The handle is returned locked and with its refCount incremented.
  819.  *    It should be released with Fsutil_HandleRelease.
  820.  *
  821.  *----------------------------------------------------------------------
  822.  */
  823.  
  824. Fs_HandleHeader *
  825. FspdevRmtPseudoStreamVerify(fileIDPtr, clientID, domainTypePtr)
  826.     Fs_FileID    *fileIDPtr;    /* Client's I/O file ID */
  827.     int        clientID;    /* Host ID of the client */
  828.     int        *domainTypePtr;    /* Return - FS_PSEUDO_DOMAIN */
  829. {
  830.     register Fspdev_ClientIOHandle    *cltHandlePtr;
  831.     register Fsconsist_ClientInfo    *clientPtr;
  832.     Boolean            found = FALSE;
  833.  
  834.     if (fileIDPtr->type > 0 && fileIDPtr->type < FSIO_NUM_STREAM_TYPES) {
  835.     fileIDPtr->type = fsio_RmtToLclType[fileIDPtr->type];
  836.     }
  837.     if (fileIDPtr->type != FSIO_LCL_PSEUDO_STREAM &&
  838.     fileIDPtr->type != FSIO_LCL_PFS_STREAM) {
  839.     printf( "FspdevRmtPseudoStreamVerify, bad type <%d>\n",
  840.         fileIDPtr->type);
  841.     return((Fs_HandleHeader *)NIL);
  842.     }
  843.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, fileIDPtr);
  844.     if (cltHandlePtr != (Fspdev_ClientIOHandle *)NIL) {
  845.     LIST_FORALL(&cltHandlePtr->clientList, (List_Links *) clientPtr) {
  846.         if (clientPtr->clientID == clientID) {
  847.         found = TRUE;
  848.         break;
  849.         }
  850.     }
  851.     if (!found) {
  852.         Fsutil_HandleRelease(cltHandlePtr, TRUE);
  853.         cltHandlePtr = (Fspdev_ClientIOHandle *)NIL;
  854.     }
  855.     }
  856.     if (!found) {
  857.     printf(
  858.         "FspdevRmtPseudoStreamVerify, client %d not known for %s <%x,%x>\n",
  859.         clientID, Fsutil_FileTypeToString(fileIDPtr->type),
  860.         fileIDPtr->major, fileIDPtr->minor);
  861.     }
  862.     if (domainTypePtr != (int *)NIL) {
  863.     *domainTypePtr = FS_PSEUDO_DOMAIN;
  864.     }
  865.     return((Fs_HandleHeader *)cltHandlePtr);
  866. }
  867.